home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 15 / CU Amiga Magazine's Super CD-ROM 15 (1997)(EMAP Images)(GB)[!][issue 1997-10].iso / CUCD / Graphics / Ghostscript / source / gxclist.c < prev    next >
C/C++ Source or Header  |  1997-05-21  |  26KB  |  863 lines

  1. /* Copyright (C) 1991, 1996, 1997 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* gxclist.c */
  20. /* Command list writing for Ghostscript. */
  21. #include "memory_.h"
  22. #include "gx.h"
  23. #include "gp.h"
  24. #include "gpcheck.h"
  25. #include "gserrors.h"
  26. #include "gxdevice.h"
  27. #include "gxdevmem.h"            /* must precede gxcldev.h */
  28. #include "gxcldev.h"
  29.  
  30. #define cdev cwdev
  31.  
  32. /* Forward declarations of procedures */
  33. private dev_proc_open_device(clist_open);
  34. private dev_proc_output_page(clist_output_page);
  35. private dev_proc_open_device(clist_close);
  36. private dev_proc_get_band(clist_get_band);
  37. /* In gxclrect.c */
  38. extern dev_proc_fill_rectangle(clist_fill_rectangle);
  39. extern dev_proc_copy_mono(clist_copy_mono);
  40. extern dev_proc_copy_color(clist_copy_color);
  41. extern dev_proc_copy_alpha(clist_copy_alpha);
  42. extern dev_proc_strip_tile_rectangle(clist_strip_tile_rectangle);
  43. extern dev_proc_strip_copy_rop(clist_strip_copy_rop);
  44. /* In gxclread.c */
  45. extern dev_proc_get_bits(clist_get_bits);
  46.  
  47. /* The device procedures */
  48. gx_device_procs gs_clist_device_procs =
  49. {    clist_open,
  50.     gx_forward_get_initial_matrix,
  51.     gx_default_sync_output,
  52.     clist_output_page,
  53.     clist_close,
  54.     gx_forward_map_rgb_color,
  55.     gx_forward_map_color_rgb,
  56.     clist_fill_rectangle,
  57.     gx_default_tile_rectangle,
  58.     clist_copy_mono,
  59.     clist_copy_color,
  60.     gx_default_draw_line,
  61.     clist_get_bits,
  62.     gx_forward_get_params,
  63.     gx_forward_put_params,
  64.     gx_forward_map_cmyk_color,
  65.     gx_forward_get_xfont_procs,
  66.     gx_forward_get_xfont_device,
  67.     gx_forward_map_rgb_alpha_color,
  68.     gx_forward_get_page_device,
  69.     gx_forward_get_alpha_bits,
  70.     clist_copy_alpha,
  71.     clist_get_band,
  72.     gx_default_copy_rop,
  73.     gx_default_fill_path,
  74.     gx_default_stroke_path,
  75.     gx_default_fill_mask,
  76.     gx_default_fill_trapezoid,
  77.     gx_default_fill_parallelogram,
  78.     gx_default_fill_triangle,
  79.     gx_default_draw_thin_line,
  80.     gx_default_begin_image,
  81.     gx_default_image_data,
  82.     gx_default_end_image,
  83.     clist_strip_tile_rectangle,
  84.     clist_strip_copy_rop,
  85.     gx_forward_get_clipping_box
  86. };
  87.  
  88. /* ------ Define the command set and syntax ------ */
  89.  
  90. /* Define the clipping enable/disable opcodes. */
  91. /* The path extensions initialize these to their proper values. */
  92. byte cmd_opvar_disable_clip = 0xff;
  93. byte cmd_opvar_enable_clip = 0xff;
  94.  
  95. #ifdef DEBUG
  96. const char *cmd_op_names[16] = { cmd_op_name_strings };
  97. private const char *cmd_misc_op_names[16] = { cmd_misc_op_name_strings };
  98. const char **cmd_sub_op_names[16] =
  99. {    cmd_misc_op_names, 0, 0, 0, 0, 0, 0, 0,
  100.     0, 0, 0, 0, 0, 0, 0, 0
  101. };
  102. private ulong far_data cmd_op_counts[256];
  103. private ulong far_data cmd_op_sizes[256];
  104. private ulong cmd_tile_reset, cmd_tile_found, cmd_tile_added;
  105. extern ulong cmd_diffs[5];        /* in gxclpath.c */
  106. private ulong cmd_same_band, cmd_other_band;
  107. int
  108. cmd_count_op(int op, uint size)
  109. {    cmd_op_counts[op]++;
  110.     cmd_op_sizes[op] += size;
  111.     if ( gs_debug_c('L') )
  112.       { const char **sub = cmd_sub_op_names[op >> 4];
  113.         if ( sub )
  114.           dprintf2(", %s(%u)\n", sub[op & 0xf], size);
  115.         else
  116.           dprintf3(", %s %d(%u)\n", cmd_op_names[op >> 4], op & 0xf, size);
  117.         fflush(dstderr);
  118.       }
  119.     return op;
  120. }
  121. void
  122. cmd_uncount_op(int op, uint size)
  123. {    cmd_op_counts[op]--;
  124.     cmd_op_sizes[op] -= size;
  125. }
  126. #endif
  127.  
  128. /* Initialization for imager state. */
  129. /* The initial scale is arbitrary. */
  130. const gs_imager_state clist_imager_state_initial =
  131.  { gs_imager_state_initial(300.0 / 72.0) };
  132.  
  133. /*
  134.  * The buffer area (data, data_size) holds a bitmap cache when both writing
  135.  * and reading.  The rest of the space is used for the command buffer and
  136.  * band state bookkeeping when writing, and for the rendering buffer (image
  137.  * device) when reading.  For the moment, we divide the space up
  138.  * arbitrarily, except that we allocate less space for the bitmap cache if
  139.  * the device doesn't need halftoning.
  140.  *
  141.  * All the routines for allocating tables in the buffer are idempotent, so
  142.  * they can be used to check whether a given-size buffer is large enough.
  143.  */
  144.  
  145. /*
  146.  * Calculate the desired size for the tile cache.
  147.  */
  148. private uint
  149. clist_tile_cache_size(const gx_device *target, uint data_size)
  150. {    uint bits_size =
  151.       (data_size / 5) & -align_cached_bits_mod;  /* arbitrary */
  152.  
  153.     if ( (gx_device_has_color(target) ? target->color_info.max_color :
  154.           target->color_info.max_gray) >= 31
  155.        )
  156.       { /* No halftones -- cache holds only Patterns & characters. */
  157.         bits_size -= bits_size >> 2;
  158.       }
  159. #define min_bits_size 1024
  160.       if ( bits_size < min_bits_size )
  161.         bits_size = min_bits_size;
  162. #undef min_bits_size
  163.     return bits_size;
  164. }
  165.  
  166. /*
  167.  * Initialize the allocation for the tile cache.  Sets: tile_hash_mask,
  168.  * tile_max_count, tile_table, chunk (structure), bits (structure).
  169.  */
  170. private int
  171. clist_init_tile_cache(gx_device *dev, byte *init_data, ulong data_size)
  172. {    byte *data = init_data;
  173.     uint bits_size = data_size;
  174.     /*
  175.      * Partition the bits area between the hash table and the actual
  176.      * bitmaps.  The per-bitmap overhead is about 24 bytes; if the
  177.      * average character size is 10 points, its bitmap takes about 24 +
  178.      * 0.5 * 10/72 * xdpi * 10/72 * ydpi / 8 bytes (the 0.5 being a
  179.      * fudge factor to account for characters being narrower than they
  180.      * are tall), which gives us a guideline for the size of the hash
  181.      * table.
  182.      */
  183.     uint avg_char_size =
  184.       (uint)(dev->x_pixels_per_inch * dev->y_pixels_per_inch *
  185.          (0.5 * 10/72 * 10/72 / 8)) + 24;
  186.     uint hc = bits_size / avg_char_size;
  187.     uint hsize;
  188.  
  189.     while ( (hc + 1) & hc )
  190.       hc |= hc >> 1;    /* make mask (power of 2 - 1) */
  191.     if ( hc < 0xff )
  192.       hc = 0xff;        /* make allowance for halftone tiles */
  193.     else if ( hc > 0xfff )
  194.       hc = 0xfff;        /* cmd_op_set_tile_index has 12-bit operand */
  195.     /* Make sure the tables will fit. */
  196.     while ( hc >= 3 && (hsize = (hc + 1) * sizeof(tile_hash)) >= bits_size )
  197.       hc >>= 1;
  198.     if ( hc < 3 )
  199.       return_error(gs_error_rangecheck);
  200.     cdev->tile_hash_mask = hc;
  201.     cdev->tile_max_count = hc - (hc >> 2);
  202.     cdev->tile_table = (tile_hash *)data;
  203.     data += hsize;
  204.     bits_size -= hsize;
  205.     gx_bits_cache_chunk_init(&cdev->chunk, data, bits_size);
  206.     gx_bits_cache_init(&cdev->bits, &cdev->chunk);
  207.     return 0;
  208. }
  209.  
  210. /*
  211.  * Initialize the allocation for the bands.  Requires: target.  Sets:
  212.  * page_band_height (=page_info.band_params.BandHeight), nbands.
  213.  */
  214. private int
  215. clist_init_bands(gx_device *dev, uint data_size, int band_width,
  216.   int band_height)
  217. {    gx_device *target = cdev->target;
  218.     int nbands;
  219.  
  220.     if ( gdev_mem_data_size((gx_device_memory *)target, band_width,
  221.                 band_height) > data_size
  222.        )
  223.       return_error(gs_error_rangecheck);
  224.     cdev->page_band_height = band_height;
  225.     nbands = (target->height + band_height - 1) / band_height;
  226.     cdev->nbands = nbands;
  227. #ifdef DEBUG
  228.     if ( gs_debug_c('l') | gs_debug_c(':') )
  229.       dprintf4("[l]width=%d, band_width=%d, band_height=%d, nbands=%d\n",
  230.            target->width, band_width, band_height, nbands);
  231. #endif
  232.     return 0;
  233. }
  234.  
  235. /*
  236.  * Initialize the allocation for the band states, which are used only
  237.  * when writing.  Requires: nbands.  Sets: states, cbuf, cend.
  238.  */
  239. private int
  240. clist_init_states(gx_device *dev, byte *init_data, uint data_size)
  241. {    ulong state_size = cdev->nbands * (ulong)sizeof(gx_clist_state);
  242.  
  243.     /*
  244.      * The +100 in the next line is bogus, but we don't know what the
  245.      * real check should be.
  246.      */
  247.     if ( state_size + sizeof(cmd_prefix) + cmd_largest_size + 100 > data_size )
  248.       return_error(gs_error_rangecheck);
  249.     cdev->states = (gx_clist_state *)init_data;
  250.     cdev->cbuf = init_data + state_size;
  251.     cdev->cend = init_data + data_size;
  252.     return 0;
  253. }
  254.  
  255. /*
  256.  * Initialize all the data allocations.  Requires: target.  Sets:
  257.  * page_tile_cache_size, page_info.band_params.BandWidth,
  258.  * page_info.band_params.BandBufferSpace, + see above.
  259.  */
  260. private int
  261. clist_init_data(gx_device *dev, byte *init_data, uint data_size)
  262. {    gx_device *target = cdev->target;
  263.     const int band_width =
  264.       cdev->page_info.band_params.BandWidth =
  265.         (cdev->band_params.BandWidth ? cdev->band_params.BandWidth :
  266.          target->width);
  267.     int band_height = cdev->band_params.BandHeight;
  268.     const uint band_space =
  269.       cdev->page_info.band_params.BandBufferSpace =
  270.         (cdev->band_params.BandBufferSpace ?
  271.          cdev->band_params.BandBufferSpace : data_size);
  272.     byte *data = init_data;
  273.     uint size = band_space;
  274.     uint bits_size;
  275.     int code;
  276.       
  277.     if ( band_height )
  278.       { /*
  279.          * The band height is fixed, so the band buffer requirement
  280.          * is completely determined.
  281.          */
  282.         uint band_data_size =
  283.           gdev_mem_data_size((gx_device_memory *)target,
  284.                  band_width, band_height);
  285.  
  286.         if ( band_data_size >= band_space )
  287.           return_error(gs_error_rangecheck);
  288.         bits_size = min(band_space - band_data_size, data_size >> 1);
  289.       }
  290.     else
  291.       { /*
  292.          * Choose the largest band height that will fit in the
  293.          * rendering-time buffer.
  294.          */
  295.         bits_size = clist_tile_cache_size(target, band_space);
  296.         bits_size = min(bits_size, data_size >> 1);
  297.         band_height = gdev_mem_max_height((gx_device_memory *)target,
  298.                           band_width,
  299.                           band_space - bits_size);
  300.         if ( band_height == 0 )
  301.           return_error(gs_error_rangecheck);
  302.       }
  303.     code = clist_init_tile_cache(dev, data, bits_size);
  304.     if ( code < 0 )
  305.       return code;
  306.     cdev->page_tile_cache_size = bits_size;
  307.     data += bits_size;
  308.     size -= bits_size;
  309.     code = clist_init_bands(dev, size, band_width, band_height);
  310.     if ( code < 0 )
  311.       return code;
  312.     return clist_init_states(dev, data, data_size - bits_size);
  313. }
  314. /*
  315.  * Initialize the device state (for writing).  This routine requires only
  316.  * data, data_size, and target to be set, and is idempotent.
  317.  */
  318. private int
  319. clist_init(gx_device *dev)
  320. {    int code = clist_init_data(dev, cdev->data, cdev->data_size);
  321.     int nbands = cdev->nbands;
  322.  
  323.     if ( code < 0 )
  324.       return code;
  325.     /* Now initialize the rest of the state. */
  326.     cdev->ymin = cdev->ymax = -1;    /* render_init not done yet */
  327.     memset(cdev->tile_table, 0, (cdev->tile_hash_mask + 1) *
  328.            sizeof(*cdev->tile_table));
  329.     cdev->cnext = cdev->cbuf;
  330.     cdev->ccl = 0;
  331.     cdev->band_range_list.head = cdev->band_range_list.tail = 0;
  332.     cdev->band_range_min = 0;
  333.     cdev->band_range_max = nbands - 1;
  334.     { int band;
  335.       gx_clist_state *states = cdev->states;
  336.  
  337.       for ( band = 0; band < nbands; band++, states++ )
  338.         { static const gx_clist_state cls_initial =
  339.             { cls_initial_values };
  340.           *states = cls_initial;
  341.         }
  342.     }
  343.     /*
  344.      * Round up the size of the per-tile band mask so that the bits,
  345.      * which follow it, stay aligned.
  346.      */
  347.     cdev->tile_band_mask_size =
  348.       ((nbands + (align_bitmap_mod * 8 - 1)) >> 3) &
  349.         ~(align_bitmap_mod - 1);
  350.     /*
  351.      * Initialize the all-band parameters to impossible values,
  352.      * to force them to be written the first time they are used.
  353.      */
  354.     memset(&cdev->tile_params, 0, sizeof(cdev->tile_params));
  355.     cdev->tile_depth = 0;
  356.     cdev->tile_known_min = nbands;
  357.     cdev->tile_known_max = -1;
  358.     cdev->imager_state = clist_imager_state_initial;
  359.     cdev->clip_path = NULL;
  360.     cdev->clip_path_id = gs_no_id;
  361.     cdev->color_space = 0;
  362.     { int i;
  363.       for ( i = 0; i < countof(cdev->transfer_ids); ++i )
  364.         cdev->transfer_ids[i] = gs_no_id;
  365.     }
  366.     cdev->black_generation_id = gs_no_id;
  367.     cdev->undercolor_removal_id = gs_no_id;
  368.     cdev->device_halftone_id = gs_no_id;
  369.     cdev->in_image = false;
  370.     return 0;
  371. }
  372. /* Open the device by initializing the device state and opening the */
  373. /* scratch files. */
  374. private int
  375. clist_open(gx_device *dev)
  376. {    char fmode[4];
  377.     int code;
  378.  
  379.     cdev->page_cfile = 0;    /* in case of failure */
  380.     cdev->page_bfile = 0;    /* ditto */
  381.     code = clist_init(dev);
  382.     if ( code < 0 )
  383.       return code;
  384.     strcpy(fmode, "w+");
  385.     strcat(fmode, gp_fmode_binary_suffix);
  386.     cdev->page_cfname[0] = 0;    /* create a new file */
  387.     cdev->page_bfname[0] = 0;    /* ditto */
  388.     cdev->page_bfile_end_pos = 0;
  389.     if ( (code = clist_fopen(cdev->page_cfname, fmode, &cdev->page_cfile,
  390.                  &gs_memory_default, true)) < 0 ||
  391.          (code = clist_fopen(cdev->page_bfname, fmode, &cdev->page_bfile,
  392.                  &gs_memory_default, true)) < 0
  393.        )
  394.       clist_close(dev);
  395.     return code;
  396. }
  397.  
  398. /* The output_page procedure should never be called! */
  399. private int
  400. clist_output_page(gx_device *dev, int num_copies, int flush)
  401. {    return_error(gs_error_Fatal);
  402. }
  403.  
  404. /* Reset (or prepare to append to) the command list after printing a page. */
  405. int
  406. clist_finish_page(gx_device *dev, bool flush)
  407. {    if ( flush )
  408.       { clist_rewind(cdev->page_cfile, true, cdev->page_cfname);
  409.         clist_rewind(cdev->page_bfile, true, cdev->page_bfname);
  410.         cdev->page_bfile_end_pos = 0;
  411.       }
  412.     else
  413.       { clist_fseek(cdev->page_cfile, 0L, SEEK_END, cdev->page_cfname);
  414.         clist_fseek(cdev->page_bfile, 0L, SEEK_END, cdev->page_bfname);
  415.       }
  416.     return clist_init(dev);        /* reinitialize */
  417. }
  418.  
  419. /* Close the device by freeing the temporary files. */
  420. /* Note that this does not deallocate the buffer. */
  421. private int
  422. clist_close(gx_device *dev)
  423. {    if ( cdev->page_cfile != NULL )
  424.       {    clist_fclose(cdev->page_cfile, cdev->page_cfname, true);
  425.         cdev->page_cfile = NULL;
  426.       }
  427.     if ( cdev->page_bfile != NULL )
  428.       {    clist_fclose(cdev->page_bfile, cdev->page_bfname, true);
  429.         cdev->page_bfile = NULL;
  430.       }
  431.     return 0;
  432. }
  433.  
  434. /* Print statistics. */
  435. #ifdef DEBUG
  436. void
  437. cmd_print_stats(void)
  438. {    int ci, cj;
  439.     dprintf3("[l]counts: reset = %lu, found = %lu, added = %lu\n",
  440.              cmd_tile_reset, cmd_tile_found, cmd_tile_added);
  441.     dprintf5("     diff 2.5 = %lu, 3 = %lu, 4 = %lu, 2 = %lu, >4 = %lu\n",
  442.          cmd_diffs[0], cmd_diffs[1], cmd_diffs[2], cmd_diffs[3],
  443.          cmd_diffs[4]);
  444.     dprintf2("     same_band = %lu, other_band = %lu\n",
  445.          cmd_same_band, cmd_other_band);
  446.     for ( ci = 0; ci < 0x100; ci += 0x10 )
  447.        {    const char **sub = cmd_sub_op_names[ci >> 4];
  448.         if ( sub != 0 )
  449.           { dprintf1("[l]  %s =", cmd_op_names[ci >> 4]);
  450.             for ( cj = ci; cj < ci + 0x10; cj += 2 )
  451.               dprintf6("\n\t%s = %lu(%lu), %s = %lu(%lu)",
  452.                    sub[cj-ci],
  453.                    cmd_op_counts[cj], cmd_op_sizes[cj],
  454.                    sub[cj-ci+1],
  455.                    cmd_op_counts[cj+1], cmd_op_sizes[cj+1]);
  456.           }
  457.         else
  458.           { ulong tcounts = 0, tsizes = 0;
  459.             for ( cj = ci; cj < ci + 0x10; cj++ )
  460.               tcounts += cmd_op_counts[cj],
  461.               tsizes += cmd_op_sizes[cj];
  462.             dprintf3("[l]  %s (%lu,%lu) =\n\t",
  463.                  cmd_op_names[ci >> 4], tcounts, tsizes);
  464.             for ( cj = ci; cj < ci + 0x10; cj++ )
  465.               if ( cmd_op_counts[cj] == 0 )
  466.             dputs(" -");
  467.               else
  468.             dprintf2(" %lu(%lu)", cmd_op_counts[cj],
  469.                  cmd_op_sizes[cj]);
  470.           }
  471.         dputs("\n");
  472.        }
  473. }
  474. #endif                /* DEBUG */
  475.  
  476. /* ------ Writing ------ */
  477.  
  478. /* Utilities */
  479.  
  480. /* Write the commands for one band or band range. */
  481. private int
  482. cmd_write_band(gx_device_clist_writer *cldev, int band_min, int band_max,
  483.   cmd_list *pcl, byte cmd_end)
  484. {    const cmd_prefix *cp = pcl->head;
  485.  
  486.     if ( cp != 0 || cmd_end != cmd_opv_end_run ) {
  487.       clist_file_ptr cfile = cldev->page_cfile;
  488.       clist_file_ptr bfile = cldev->page_bfile;
  489.       cmd_block cb;
  490.       byte end = cmd_count_op(cmd_end, 1);
  491.       int code;
  492.  
  493.       cb.band_min = band_min;
  494.       cb.band_max = band_max;
  495.       cb.pos = clist_ftell(cfile);
  496.       if_debug3('l', "[l]writing for bands (%d,%d) at %ld\n",
  497.             band_min, band_max, cb.pos);
  498.       clist_fwrite_chars(&cb, sizeof(cb), bfile);
  499.       if ( cp != 0 ) {
  500.         pcl->tail->next = 0;    /* terminate the list */
  501.         for ( ; cp != 0; cp = cp->next ) {
  502. #ifdef DEBUG
  503.           if ( (const byte *)cp < cldev->cbuf ||
  504.            (const byte *)cp >= cldev->cend ||
  505.            cp->size > cldev->cend - (const byte *)cp
  506.          ) {
  507.         lprintf1("cmd_write_band error at 0x%lx\n", (ulong)cp);
  508.         return_error(gs_error_Fatal);
  509.           }
  510. #endif
  511.           clist_fwrite_chars(cp + 1, cp->size, cfile);
  512.         }
  513.         pcl->head = pcl->tail = 0;
  514.       }
  515.  
  516.       clist_fwrite_chars(&end, 1, cfile);
  517.       process_interrupts();
  518.       if ( (code = clist_ferror_code(bfile)) < 0 ||
  519.            (code = clist_ferror_code(cfile)) < 0
  520.          )
  521.         return_error(code);
  522.     }
  523.     return 0;
  524. }
  525.  
  526. /* Write out the buffered commands, and reset the buffer. */
  527. private int
  528. cmd_write_buffer(gx_device_clist_writer *cldev, byte cmd_end)
  529. {    int nbands = cldev->nbands;
  530.     gx_clist_state *pcls;
  531.     int band;
  532.     int code = cmd_write_band(cldev, cldev->band_range_min,
  533.                   cldev->band_range_max,
  534.                   &cldev->band_range_list, cmd_opv_end_run);
  535.  
  536.     for ( band = 0, pcls = cldev->states;
  537.           code >= 0 && band < nbands; band++, pcls++
  538.         )
  539.       code = cmd_write_band(cldev, band, band, &pcls->list, cmd_end);
  540.     cldev->cnext = cldev->cbuf;
  541.     cldev->ccl = 0;
  542.     cldev->band_range_list.head = cldev->band_range_list.tail = 0;
  543. #ifdef DEBUG
  544.     if ( gs_debug_c('l') )
  545.       cmd_print_stats();
  546. #endif
  547.     return_check_interrupt(code);
  548. }
  549. /* End a page by flushing the buffer and terminating the command list. */
  550. int
  551. clist_end_page(gx_device_clist_writer *cldev)
  552. {    int code = cmd_write_buffer(cldev, cmd_opv_end_page);
  553.     cmd_block cb;
  554.  
  555.     if ( code < 0 )
  556.       return code;
  557.     /* Write the terminating entry in the block file. */
  558.     /* Note that because of copypage, there may be many such entries. */
  559.     cb.band_min = cb.band_max = cmd_band_end;
  560.     cb.pos = clist_ftell(cldev->page_cfile);
  561.     clist_fwrite_chars(&cb, sizeof(cb), cldev->page_bfile);
  562.     cldev->page_bfile_end_pos = clist_ftell(cldev->page_bfile);
  563. #ifdef DEBUG
  564.     if ( gs_debug_c('l') | gs_debug_c(':') )
  565.       dprintf2("[l]clist_render_init at cfile=%ld, bfile=%ld\n",
  566.            cb.pos, cldev->page_bfile_end_pos);
  567. #endif
  568.     return 0;
  569. }
  570.  
  571. /* Add a command to the appropriate band list, */
  572. /* and allocate space for its data. */
  573. /* Return the pointer to the data area. */
  574. /* If an error occurs, set cldev->error_code and return 0. */
  575. #define cmd_headroom (sizeof(cmd_prefix) + arch_align_ptr_mod)
  576. byte *
  577. cmd_put_list_op(gx_device_clist_writer *cldev, cmd_list *pcl, uint size)
  578. {    byte *dp = cldev->cnext;
  579.     if ( size + cmd_headroom > cldev->cend - dp )
  580.       { int code = cldev->error_code =
  581.           cmd_write_buffer(cldev, cmd_opv_end_run);
  582.         if ( code < 0 )
  583.           return 0;
  584.         return cmd_put_list_op(cldev, pcl, size);
  585.       }
  586.     if ( cldev->ccl == pcl )
  587.       { /* We're adding another command for the same band. */
  588.         /* Tack it onto the end of the previous one. */
  589.         cmd_count_add1(cmd_same_band);
  590. #ifdef DEBUG
  591.         if ( pcl->tail->size > dp - (byte *)(pcl->tail + 1) )
  592.           { lprintf1("cmd_put_list_op error at 0x%lx\n", (ulong)pcl->tail);
  593.           }
  594. #endif
  595.         pcl->tail->size += size;
  596.       }
  597.     else
  598.       { /* Skip to an appropriate alignment boundary. */
  599.         /* (We assume the command buffer itself is aligned.) */
  600.         cmd_prefix *cp =
  601.           (cmd_prefix *)(dp +
  602.                  ((cldev->cbuf - dp) & (arch_align_ptr_mod - 1)));
  603.         cmd_count_add1(cmd_other_band);
  604.         dp = (byte *)(cp + 1);
  605.         if ( pcl->tail != 0 )
  606.           {
  607. #ifdef DEBUG
  608.         if ( pcl->tail < pcl->head ||
  609.              pcl->tail->size > dp - (byte *)(pcl->tail + 1)
  610.            )
  611.           { lprintf1("cmd_put_list_op error at 0x%lx\n",
  612.                  (ulong)pcl->tail);
  613.           }
  614. #endif
  615.         pcl->tail->next = cp;
  616.           }
  617.         else
  618.           pcl->head = cp;
  619.         pcl->tail = cp;
  620.         cldev->ccl = pcl;
  621.         cp->size = size;
  622.       }
  623.     cldev->cnext = dp + size;
  624.     return dp;
  625. }
  626. #ifdef DEBUG
  627. byte *
  628. cmd_put_op(gx_device_clist_writer *cldev, gx_clist_state *pcls, uint size)
  629. {    if_debug3('L', "[L]band %d: size=%u, left=%u",
  630.           (int)(pcls - cldev->states),
  631.           size, (uint)(cldev->cend - cldev->cnext));
  632.     return cmd_put_list_op(cldev, &pcls->list, size);
  633. }
  634. #endif
  635.  
  636. /* Add a command for a range of bands. */
  637. byte *
  638. cmd_put_range_op(gx_device_clist_writer *cldev, int band_min, int band_max,
  639.   uint size)
  640. {    cmd_prefix *tail;
  641.     if_debug4('L', "[L]band range(%d,%d): size=%u, left=%u",
  642.           band_min, band_max, size,
  643.           (uint)(cldev->cend - cldev->cnext));
  644.     if ( cldev->band_range_list.head == 0 ||
  645.          band_min != cldev->band_range_min ||
  646.          band_max != cldev->band_range_max ||
  647.          (tail = cldev->band_range_list.tail,
  648.           cldev->cnext != (byte *)(tail + 1) + tail->size)
  649.        )
  650.       { if ( (cldev->error_code = cmd_write_buffer(cldev, cmd_opv_end_run)) < 0 )
  651.           return 0;
  652.         cldev->band_range_min = band_min;
  653.         cldev->band_range_max = band_max;
  654.       }
  655.     return cmd_put_list_op(cldev, &cldev->band_range_list, size);
  656. }
  657.  
  658. /* Write a variable-size positive integer. */
  659. int
  660. cmd_size_w(register uint w)
  661. {    register int size = 1;
  662.     while ( w > 0x7f ) w >>= 7, size++;
  663.     return size;
  664. }
  665. byte *
  666. cmd_put_w(register uint w, register byte *dp)
  667. {    while ( w > 0x7f ) *dp++ = w | 0x80, w >>= 7;
  668.     *dp = w;
  669.     return dp + 1;
  670. }
  671.  
  672. /* Define the encodings of the different settable colors. */
  673. const clist_select_color_t
  674.   clist_select_color0 = {cmd_op_set_color0, cmd_opv_delta2_color0, 0},
  675.   clist_select_color1 = {cmd_op_set_color1, cmd_opv_delta2_color1, 0},
  676.   clist_select_tile_color0 = {cmd_op_set_color0, cmd_opv_delta2_color0, 1},
  677.   clist_select_tile_color1 = {cmd_op_set_color1, cmd_opv_delta2_color1, 1};
  678. int
  679. cmd_put_color(gx_device_clist_writer *cldev, gx_clist_state *pcls,
  680.   const clist_select_color_t *select,
  681.   gx_color_index color, gx_color_index *pcolor)
  682. {    byte *dp;
  683.     long diff = (long)color - (long)(*pcolor);
  684.     byte op, op_delta2;
  685.  
  686.     if ( diff == 0 )
  687.       return 0;
  688.     if ( select->tile_color )
  689.       set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_tile_color, 1);
  690.     op = select->set_op;
  691.     op_delta2 = select->delta2_op;
  692.     if ( color == gx_no_color_index )
  693.       {    /*
  694.          * We must handle this specially, because it may take more
  695.          * bytes than the color depth.
  696.          */
  697.         set_cmd_put_op(dp, cldev, pcls, op + 15, 1);
  698.       }
  699.     else
  700.        {    long delta;
  701.         byte operand;
  702.  
  703.         switch ( (cldev->color_info.depth + 15) >> 3 )
  704.           {
  705.           case 5:
  706.             if ( !((delta = diff + cmd_delta1_32_bias) &
  707.                   ~cmd_delta1_32_mask) &&
  708.                  (operand =
  709.                   (byte)((delta >> 23) + ((delta >> 18) & 1))) != 0 &&
  710.                  operand != 15
  711.                )
  712.               { set_cmd_put_op(dp, cldev, pcls,
  713.                        (byte)(op + operand), 2);
  714.                 dp[1] = (byte)(((delta >> 10) & 0300) +
  715.                        (delta >> 5) + delta);
  716.                 break;
  717.               }
  718.               if ( !((delta = diff + cmd_delta2_32_bias) &
  719.                    ~cmd_delta2_32_mask)
  720.                )
  721.               { set_cmd_put_op(dp, cldev, pcls, op_delta2, 3);
  722.                 dp[1] = (byte)((delta >> 20) + (delta >> 16));
  723.                 dp[2] = (byte)((delta >> 4) + delta);
  724.                 break;
  725.               }
  726.             set_cmd_put_op(dp, cldev, pcls, op, 5);
  727.             *++dp = (byte)(color >> 24);
  728.             goto b3;
  729.           case 4:
  730.             if ( !((delta = diff + cmd_delta1_24_bias) &
  731.                    ~cmd_delta1_24_mask) &&
  732.                  (operand = (byte)(delta >> 16)) != 0 &&
  733.                  operand != 15
  734.                )
  735.               { set_cmd_put_op(dp, cldev, pcls,
  736.                        (byte)(op + operand), 2);
  737.                 dp[1] = (byte)((delta >> 4) + delta);
  738.                 break;
  739.               }
  740.               if ( !((delta = diff + cmd_delta2_24_bias) &
  741.                    ~cmd_delta2_24_mask)
  742.                )
  743.               { set_cmd_put_op(dp, cldev, pcls, op_delta2, 3);
  744.                 dp[1] = ((byte)(delta >> 13) & 0xf8) +
  745.                   ((byte)(delta >> 11) & 7);
  746.                 dp[2] = (byte)(((delta >> 3) & 0xe0) + delta);
  747.                 break;
  748.               }
  749.             set_cmd_put_op(dp, cldev, pcls, op, 4);
  750. b3:            *++dp = (byte)(color >> 16);
  751.             goto b2;
  752.           case 3:
  753.             set_cmd_put_op(dp, cldev, pcls, op, 3);
  754. b2:            *++dp = (byte)(color >> 8);
  755.             goto b1;
  756.           case 2:
  757.             if ( diff >= -7 && diff < 7 )
  758.               { set_cmd_put_op(dp, cldev, pcls,
  759.                        op + (int)diff + 8, 1);
  760.                 break;
  761.               }
  762.             set_cmd_put_op(dp, cldev, pcls, op, 2);
  763. b1:            dp[1] = (byte)color;
  764.           }
  765.        }
  766.     *pcolor = color;
  767.     return 0;
  768. }
  769.  
  770. /* Put out a command to set the tile colors. */
  771. int
  772. cmd_set_tile_colors(gx_device_clist_writer *cldev, gx_clist_state *pcls,
  773.   gx_color_index color0, gx_color_index color1)
  774. {    if ( color0 != pcls->tile_colors[0] )
  775.        {    int code = cmd_put_color(cldev, pcls,
  776.                      &clist_select_tile_color0,
  777.                      color0, &pcls->tile_colors[0]);
  778.         if ( code < 0 )
  779.           return code;
  780.        }
  781.     if ( color1 != pcls->tile_colors[1] )
  782.        {    int code = cmd_put_color(cldev, pcls,
  783.                      &clist_select_tile_color1,
  784.                      color1, &pcls->tile_colors[1]);
  785.         if ( code < 0 )
  786.           return code;
  787.        }
  788.     return 0;
  789. }
  790.  
  791. /* Put out a command to set the tile phase. */
  792. int
  793. cmd_set_tile_phase(gx_device_clist_writer *cldev, gx_clist_state *pcls,
  794.   int px, int py)
  795. {    int pcsize;
  796.     byte *dp;
  797.  
  798.     pcls->tile_phase.x = px;
  799.     pcls->tile_phase.y = py;
  800.     pcsize = 1 + cmd_sizexy(pcls->tile_phase);
  801.     set_cmd_put_op(dp, cldev, pcls, (byte)cmd_opv_set_tile_phase, pcsize);
  802.     ++dp;
  803.     cmd_putxy(pcls->tile_phase, dp);
  804.     return 0;
  805. }
  806.  
  807. /* Write a command to enable or disable the logical operation. */
  808. int
  809. cmd_put_enable_lop(gx_device_clist_writer *cldev, gx_clist_state *pcls,
  810.   int enable)
  811. {    byte *dp;
  812.     set_cmd_put_op(dp, cldev, pcls,
  813.                (byte)(enable ? cmd_opv_enable_lop :
  814.                   cmd_opv_disable_lop),
  815.                1);
  816.     pcls->lop_enabled = enable;
  817.     return 0;
  818. }
  819.  
  820. /* Write a command to enable or disable clipping. */
  821. /* This routine is only called if the path extensions are included. */
  822. int
  823. cmd_put_enable_clip(gx_device_clist_writer *cldev, gx_clist_state *pcls,
  824.   int enable)
  825. {    byte *dp;
  826.     set_cmd_put_op(dp, cldev, pcls,
  827.                (byte)(enable ? cmd_opvar_enable_clip :
  828.                   cmd_opvar_disable_clip),
  829.                1);
  830.     pcls->clip_enabled = enable;
  831.     return 0;
  832. }
  833.  
  834. /* Write a command to set the logical operation. */
  835. int
  836. cmd_set_lop(gx_device_clist_writer *cldev, gx_clist_state *pcls,
  837.   gs_logical_operation_t lop)
  838. {    byte *dp;
  839.     uint lop_msb = lop >> 6;
  840.  
  841.     set_cmd_put_op(dp, cldev, pcls,
  842.                cmd_opv_set_misc, 2 + cmd_size_w(lop_msb));
  843.     dp[1] = cmd_set_misc_lop + (lop & 0x3f);
  844.     cmd_put_w(lop_msb, dp + 2);
  845.     pcls->lop = lop;
  846.     return 0;
  847. }
  848.  
  849. /* ---------------- Driver interface ---------------- */
  850.  
  851. private int
  852. clist_get_band(gx_device *dev, int y, int *band_start)
  853. {    int band_height = cdev->page_band_height;
  854.     int start;
  855.  
  856.     if ( y < 0 )
  857.       y = 0;
  858.     else if ( y >= dev->height )
  859.       y = dev->height;
  860.     *band_start = start = y - y % band_height;
  861.     return min(dev->height - start, band_height);
  862. }
  863.